package cn.wizzer.app.web.modules.controllers.platform.user;

import cn.wizzer.app.user.modules.models.User;
import cn.wizzer.app.user.modules.services.UserService;
import cn.wizzer.app.web.commons.ulog.annotation.SLog;
import cn.wizzer.app.web.commons.utils.StringUtil;
import cn.wizzer.framework.base.model.enums.BizExceptionEnum;
import cn.wizzer.framework.page.Pagination;
import cn.wizzer.framework.util.Result;
import cn.wizzer.framework.util.param.ParamVerify;
import com.alibaba.dubbo.config.annotation.Reference;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.util.ByteSource;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.integration.jedis.RedisService;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.Times;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import redis.clients.jedis.ScanParams;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

@IocBean
@At("/platform/user/manager")
public class UserController {
    private static final Log log = Logs.get();

    @Inject
    @Reference
    private UserService userService;

    @Inject
    private RedisService redisService;

    @At("/")
    @Ok("beetl:/platform/user/manager/index.html")
    @RequiresPermissions("user.manager.list")
    public void index() {

    }

    /**
     * 查询用户（分页）
     *
     * @param conditionData  条件集：是否主播、是否禁言等
     * @param userKeyword    String(要搜索的内容)
     * @param inviterKeyword 邀请人关键字
     * @param searchDate     String[](按日期时间搜索)
     * @param pageNumber     int
     * @param pageSize       int
     * @return Object
     */
    @At
    @Ok("json:full")
    @RequiresPermissions("user.manager.list")
    public Object data(@Param("conditionData") String conditionData,
                       @Param("userKeyword") String userKeyword,
                       @Param("inviterKeyword") String inviterKeyword,
                       @Param("searchDate") String[] searchDate,
                       @Param("pageNumber") int pageNumber,
                       @Param("pageSize") int pageSize) {
        Pagination pagination = userService.userListNew(conditionData, userKeyword, inviterKeyword, searchDate, pageNumber, pageSize);
        int onlineNum = userService.count(Cnd.where("isOnline", "=", 1));
        return Result.success().addData(Result.createMap("pagination", pagination, "onlineNum", onlineNum));
    }

    /**
     * 根据用户名精确搜索用户
     *
     * @param key
     * @return
     */
    @At
    @Ok("json:full")
    public Object list(String key) {
        Cnd cnd = Cnd.where("userName", "=", key);
        return Result.success().addData(userService.query(cnd));
    }


    /**
     * 根据币种id、用户名精确搜索用户
     *
     * @param key
     * @param currencyId
     * @return
     */
    @At("/searchAccount")
    @Ok("json:full")
    public Object searchAccount(String key, @ParamVerify(name = "currencyId", required = true) String currencyId) {
        return Result.success().addData(userService.userAccountVoList(key, currencyId));
    }


    /**
     * 添加用户
     *
     * @param user       User
     * @param inviteCode
     * @return Object
     */
    @At("/add")
    @Ok("json")
    @RequiresPermissions("user.manager.add")
    @SLog(tag = "新建User", msg = "用户名:${user.userName}, 邮箱:${user.email}")
    public Object add(@Param("..") User user, String inviteCode) {
        if (Strings.isBlank(user.getUserName())) {
            return Result.error(BizExceptionEnum.USER_NAME_CAN_NOT_BE_NULL);
        }
        String userName = Strings.trim(user.getUserName());
        String email = Strings.trim(user.getEmail());
        user.setOpBy(StringUtil.getPlatformUid());
        user.setOpAt(1L);
        user.setUserName(userName);
        user.setNickName(userName);
        user.setEmail(email);
        userService.insertUser(user, inviteCode);
        return Result.success();
    }


    /**
     * 查询用户
     *
     * @param id String
     * @return Object
     */
    @At("/edit/?")
    @Ok("json:{locked:'password|transactionPwd'}")
    public Object edit(String id) {
        return Result.success(userService.fetch(id));
    }

    /**
     * 修改用户
     *
     * @param user User
     * @return Object
     */
    @At("/editDo")
    @Ok("json")
    @RequiresPermissions("user.manager.edit")
    @SLog(tag = "修改用户", msg = "用户名:${args[0].userName}")
    public Object editDo(@Param("..") User user, String inviteCode) {
        //禁用,离线用户
        if (user.isDisabled()) {
            //扫描当前在线的用户
            redisService.del(("api_token:" + user.getId()));
            if (user.isOnline()) {
                //计算用户登录时长
                user.setLoginDuration(userService.calculateLoginDuration(user));
                //用户在线状态设置为离线
                user.setOnline(false);
            }
        }
        // 修改用户邀请人
        if (Strings.isNotBlank(inviteCode)) {
            User inviteUser = userService.fetch(Cnd.where("inviteCode", "=", inviteCode));
            if (inviteUser == null) {
                return Result.error(BizExceptionEnum.ERROR_INVITE_CODE);
            }
            if (inviteUser.getPath().contains(user.getId())) {
                return Result.error("存在上下级关系，不能被邀请");
            }
            if (user.getId().equals(inviteUser.getId())) {
                return Result.error("邀请人不能设置自己");
            }
            if (userService.count(Cnd.where("inviter", "=", user.getId())) > 0) {
                return Result.error("该用户已有下线，不能更改邀请人");
            }
            String path = inviteUser.getPath() + "/" + user.getId();
            user.setPath(path);
            user.setInviter(inviteUser.getId());
            //设置层级，为邀请人的层级 + 1
            user.setLayer(inviteUser.getLayer() + 1);
        }
        // 修改手机号
        if (Strings.isNotBlank(user.getPhone())) {
            // 查询手机号是否存在
            int num = userService.count(Cnd.where("phonePrefix", "=", user.getPhonePrefix()).and("phone", "=", user.getPhone()).and("id", "!=", user.getId()));
            if (num > 0) {
                return Result.error(BizExceptionEnum.PHONE_REGISTERED);
            }
        }
        user.setUserName(null);
        user.setEmail(null);
        user.setInviteCode(null);
        userService.updateUser(user);
        return Result.success("操作成功");
    }

    @At()
    @Ok("json")
    @RequiresPermissions("user.manager.edit")
    @SLog(tag = "用户状态")
    public Object setDisabled(@Param("id") String id, @Param("disabled") boolean disabled) {
        if (disabled) {
            //扫描当前在线的用户
            ScanParams scanParams = new ScanParams();
            scanParams.match("user:token:*");
            scanParams.count(Integer.MAX_VALUE);
            List<String> keys = redisService.scan("0", scanParams).getResult();
            //匹配该用户登录缓存
            Object[] loginKey = keys.stream().filter(key -> key.contains(id)).toArray();
            //同步将用户强行下线
            for (Object o : loginKey) {
                redisService.del(o.toString());
            }
            userService.update(Chain.make("disabled", true).add("isOnline", 0), Cnd.where("id", "=", id));
        } else {
            userService.update(Chain.make("disabled", false), Cnd.where("id", "=", id));
        }
        return Result.success();
    }


    @At()
    @Ok("json:full")
    public Object getUsers(@Param("key") String key, @Param("pageNumber") int pageNumber, @Param("pageSize") int pageSize) {
        return Result.success().addData(userService.listPage(pageNumber, pageSize,
                Cnd.where(Cnd.exps("nickName", "like", "%" + key + "%")
                        .or("userName", "like", "%" + key + "%")
                        .and("delFlag", "=", 0))));
    }


    /**
     * 删除游客账户
     *
     * @param id
     * @return
     */
    @At()
    @Ok("json")
    public Object delete(@Param("id") String id) {
        userService.deleteVisitor(id);
        return Result.success();
    }


    /**
     * 查询被邀请用户
     *
     * @param id         用户id
     * @param level      层级
     * @param pageNumber 页码
     * @param pageSize   页面条数
     * @return
     */
    @At()
    @Ok("json")
    @RequiresPermissions("user.manager.list")
    public Object invitedUser(@Param("id") String id,
                              @Param("level") Integer level,
                              @Param("inviterSearchDate") String[] searchDate,
                              @Param("pageNumber") int pageNumber,
                              @Param("pageSize") int pageSize) {
        long startTime = 0, endTime = 0;
        if (null != searchDate && searchDate.length != 0) {
            startTime = Times.d2TS(Times.D(searchDate[0]));
            endTime = Times.d2TS(Times.D(searchDate[1]));
        }
        Pagination pagination = userService.inviteList(id, level, TimeZone.getDefault().getID(), startTime, endTime, pageNumber, pageSize);
        // 所有下线充值、提现、投资的统计
        Map<String, BigDecimal> allSubReport = userService.allSubReport(id, level, startTime, endTime);
        return Result.success().addData(Result.createMap("pagination", pagination, "allSubReport", allSubReport));
    }


    /**
     * 修改内部账号交易秘密
     *
     * @param transactionPwd 交易密码
     * @return
     */
    @At()
    @Ok("json")
    @RequiresPermissions("user.manager.edit")
    public Object insideTransactionPwdEdit(@Param("transactionPwd") String transactionPwd) {
        // 获取内部账号
        List<User> userList = userService.query(Cnd.where("inside", "=", true));
        for (User user : userList) {
            if (Strings.isNotBlank(user.getSalt())) {
                // 加密交易密码
                user.setTransactionPwd(new Sha256Hash(transactionPwd, ByteSource.Util.bytes(user.getSalt()), 1024).toHex());
            }
        }
        userService.update(userList);
        return Result.success();
    }


}
